package com.example.demo.service.impl;

import com.example.demo.dto.UserLoginDto;
import com.example.demo.dto.UserProfileDto;
import com.example.demo.dto.UserRegisterDto;
import com.example.demo.entity.User;
import com.example.demo.exception.BusinessException;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import com.example.demo.service.UserStatsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 用户服务实现类
 * 实现用户相关的业务逻辑
 */
@Service
public class UserServiceImpl implements UserService {
    
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    private final UserMapper userMapper;
    private final BCryptPasswordEncoder passwordEncoder;
    private final UserStatsService userStatsService;
    
    /**
     * 构造器注入
     * @param userMapper 用户Mapper
     * @param passwordEncoder 密码编码器
     * @param userStatsService 用户统计服务
     */
    public UserServiceImpl(UserMapper userMapper, BCryptPasswordEncoder passwordEncoder, UserStatsService userStatsService) {
        this.userMapper = userMapper;
        this.passwordEncoder = passwordEncoder;
        this.userStatsService = userStatsService;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public User register(UserRegisterDto userRegisterDto) {
        log.info("开始注册用户，用户名：{}", userRegisterDto.getUsername());
        
        // 验证确认密码
        if (!userRegisterDto.getPassword().equals(userRegisterDto.getConfirmPassword())) {
            throw new BusinessException("两次输入的密码不一致");
        }
        
        // 检查用户名是否已存在
        if (isUsernameExists(userRegisterDto.getUsername())) {
            throw new BusinessException("用户名已存在");
        }
        
        // 检查邮箱是否已存在
        if (isEmailExists(userRegisterDto.getEmail())) {
            throw new BusinessException("邮箱已被注册");
        }
        
        // 检查手机号是否已存在（如果提供了手机号）
        if (userRegisterDto.getPhone() != null && isPhoneExists(userRegisterDto.getPhone())) {
            throw new BusinessException("手机号已被注册");
        }
        
        // 创建用户对象
        User user = new User();
        user.setUsername(userRegisterDto.getUsername());
        user.setPassword(passwordEncoder.encode(userRegisterDto.getPassword()));
        user.setEmail(userRegisterDto.getEmail());
        user.setPhone(userRegisterDto.getPhone());
        user.setStatus(1);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        // 保存用户
        int rows = userMapper.insert(user);
        if (rows != 1) {
            throw new BusinessException("注册失败，请稍后重试");
        }
        
        // 为新用户创建统计记录
        try {
            userStatsService.createUserStats(user.getId());
        } catch (Exception e) {
            log.warn("创建用户{}统计记录失败：{}", user.getId(), e.getMessage());
        }
        
        log.info("用户注册成功，用户ID：{}，用户名：{}", user.getId(), user.getUsername());
        
        // 返回用户信息（不含密码）
        user.setPassword(null);
        return user;
    }
    
    @Override
    public User login(UserLoginDto userLoginDto) {
        log.info("开始登录验证，用户名：{}", userLoginDto.getUsername());
        
        // 根据用户名查询用户
        User user = userMapper.selectByUsername(userLoginDto.getUsername());
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }
        
        // 验证密码
        if (!passwordEncoder.matches(userLoginDto.getPassword(), user.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        
        // 记录登录统计
        try {
            userStatsService.recordLogin(user.getId());
        } catch (Exception e) {
            log.warn("记录用户{}登录统计失败：{}", user.getId(), e.getMessage());
        }
        
        log.info("用户登录成功，用户ID：{}，用户名：{}", user.getId(), user.getUsername());
        
        // 返回用户信息（不含密码）
        user.setPassword(null);
        return user;
    }
    
    @Override
    public User getUserByUsername(String username) {
        User user = userMapper.selectByUsername(username);
        if (user != null) {
            user.setPassword(null);
        }
        return user;
    }
    
    @Override
    public User getUserById(Long id) {
        User user = userMapper.selectById(id);
        if (user != null) {
            user.setPassword(null);
        }
        return user;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public User updateUserProfile(Long userId, UserProfileDto userProfileDto) {
        log.info("开始更新用户资料，用户ID：{}", userId);
        
        // 检查用户是否存在
        User existingUser = userMapper.selectById(userId);
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查邮箱是否被其他用户使用
        if (userProfileDto.getEmail() != null && !userProfileDto.getEmail().equals(existingUser.getEmail())) {
            if (isEmailExists(userProfileDto.getEmail(), userId)) {
                throw new BusinessException("邮箱已被其他用户使用");
            }
        }
        
        // 检查手机号是否被其他用户使用
        if (userProfileDto.getPhone() != null && !userProfileDto.getPhone().equals(existingUser.getPhone())) {
            if (isPhoneExists(userProfileDto.getPhone(), userId)) {
                throw new BusinessException("手机号已被其他用户使用");
            }
        }
        
        // 如果要修改密码，先验证当前密码
        if (userProfileDto.getNewPassword() != null && !userProfileDto.getNewPassword().trim().isEmpty()) {
            if (userProfileDto.getCurrentPassword() == null || userProfileDto.getCurrentPassword().trim().isEmpty()) {
                throw new BusinessException("修改密码时必须提供当前密码");
            }
            
            // 验证当前密码是否正确
            if (!passwordEncoder.matches(userProfileDto.getCurrentPassword(), existingUser.getPassword())) {
                throw new BusinessException("当前密码不正确");
            }
            
            // 验证新密码和确认密码是否一致
            if (!userProfileDto.getNewPassword().equals(userProfileDto.getConfirmPassword())) {
                throw new BusinessException("新密码和确认密码不一致");
            }
        }
        
        // 更新用户信息
        User updateUser = new User();
        updateUser.setId(userId);
        
        if (userProfileDto.getEmail() != null) {
            updateUser.setEmail(userProfileDto.getEmail());
        }
        
        if (userProfileDto.getPhone() != null) {
            updateUser.setPhone(userProfileDto.getPhone());
        }
        
        // 如果要修改密码，设置新密码的加密值
        if (userProfileDto.getNewPassword() != null && !userProfileDto.getNewPassword().trim().isEmpty()) {
            updateUser.setPassword(passwordEncoder.encode(userProfileDto.getNewPassword()));
        }
        
        updateUser.setUpdateTime(LocalDateTime.now());
        
        // 执行更新
        int rows = userMapper.updateById(updateUser);
        if (rows != 1) {
            throw new BusinessException("更新用户资料失败");
        }
        
        log.info("用户资料更新成功，用户ID：{}", userId);
        
        // 返回更新后的用户信息
        User updatedUser = userMapper.selectById(userId);
        updatedUser.setPassword(null);
        return updatedUser;
    }
    
    @Override
    public boolean isUsernameExists(String username) {
        return userMapper.selectByUsername(username) != null;
    }
    
    @Override
    public boolean isEmailExists(String email, Long excludeUserId) {
        if (email == null || email.trim().isEmpty()) {
            return false;
        }
        return userMapper.selectByEmailExcludeUser(email, excludeUserId) != null;
    }
    
    @Override
    public boolean isEmailExists(String email) {
        return userMapper.selectByEmail(email) != null;
    }
    
    @Override
    public boolean isPhoneExists(String phone, Long excludeUserId) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }
        return userMapper.selectByPhoneExcludeUser(phone, excludeUserId) != null;
    }
    
    @Override
    public boolean isPhoneExists(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }
        return userMapper.selectByPhone(phone) != null;
    }
}
